<template>
  <div class="ssh-container">
    <el-card class="ssh-card">
      <div slot="header" class="card-header">
        <span class="card-title">
          <i class="el-icon-connection"></i>
          SSH终端
        </span>
        <div class="common-commands" @click="toggleCommands">
          <span class="commands-title">
            <i class="el-icon-document"></i>
            常用指令
            <i :class="['el-icon-arrow-down', { 'is-active': showCommands }]"></i>
          </span>
          <el-collapse-transition>
            <div v-show="showCommands" class="commands-list">
              <div class="command-category">
                <h4>文件操作</h4>
                <div class="command-item">
                  <span class="command-name">ls</span>
                  <span class="command-desc">列出目录内容</span>
                  <span class="command-example">ls -l</span>
                </div>
                <div class="command-item">
                  <span class="command-name">cd</span>
                  <span class="command-desc">切换目录</span>
                  <span class="command-example">cd /home</span>
                </div>
                <div class="command-item">
                  <span class="command-name">pwd</span>
                  <span class="command-desc">显示当前目录路径</span>
                </div>
                <div class="command-item">
                  <span class="command-name">mkdir</span>
                  <span class="command-desc">创建目录</span>
                  <span class="command-example">mkdir -p dir1/dir2</span>
                </div>
                <div class="command-item">
                  <span class="command-name">rm</span>
                  <span class="command-desc">删除文件或目录</span>
                  <span class="command-example">rm -rf dir</span>
                </div>
                <div class="command-item">
                  <span class="command-name">cp</span>
                  <span class="command-desc">复制文件或目录</span>
                  <span class="command-example">cp -r src dst</span>
                </div>
                <div class="command-item">
                  <span class="command-name">mv</span>
                  <span class="command-desc">移动或重命名文件</span>
                  <span class="command-example">mv old new</span>
                </div>
              </div>

              <div class="command-category">
                <h4>文件查看</h4>
                <div class="command-item">
                  <span class="command-name">cat</span>
                  <span class="command-desc">查看文件内容</span>
                  <span class="command-example">cat file.txt</span>
                </div>
                <div class="command-item">
                  <span class="command-name">grep</span>
                  <span class="command-desc">搜索文件内容</span>
                  <span class="command-example">grep "pattern" file</span>
                </div>
                <div class="command-item">
                  <span class="command-name">head</span>
                  <span class="command-desc">查看文件开头</span>
                  <span class="command-example">head -n 10 file</span>
                </div>
                <div class="command-item">
                  <span class="command-name">tail</span>
                  <span class="command-desc">查看文件结尾</span>
                  <span class="command-example">tail -f log.txt</span>
                </div>
                <div class="command-item">
                  <span class="command-name">less</span>
                  <span class="command-desc">分页查看文件</span>
                  <span class="command-example">less file.txt</span>
                </div>
              </div>

              <div class="command-category">
                <h4>系统监控</h4>
                <div class="command-item">
                  <span class="command-name">ps</span>
                  <span class="command-desc">查看进程状态</span>
                  <span class="command-example">ps aux</span>
                </div>
                <div class="command-item">
                  <span class="command-name">top</span>
                  <span class="command-desc">实时查看系统状态</span>
                </div>
                <div class="command-item">
                  <span class="command-name">df</span>
                  <span class="command-desc">查看磁盘使用情况</span>
                  <span class="command-example">df -h</span>
                </div>
                <div class="command-item">
                  <span class="command-name">free</span>
                  <span class="command-desc">查看内存使用情况</span>
                  <span class="command-example">free -h</span>
                </div>
                <div class="command-item">
                  <span class="command-name">netstat</span>
                  <span class="command-desc">查看网络连接状态</span>
                  <span class="command-example">netstat -tunlp</span>
                </div>
                <div class="command-item">
                  <span class="command-name">iostat</span>
                  <span class="command-desc">查看IO状态</span>
                  <span class="command-example">iostat -x 1</span>
                </div>
              </div>

              <div class="command-category">
                <h4>网络工具</h4>
                <div class="command-item">
                  <span class="command-name">ping</span>
                  <span class="command-desc">测试网络连接</span>
                  <span class="command-example">ping google.com</span>
                </div>
                <div class="command-item">
                  <span class="command-name">curl</span>
                  <span class="command-desc">发送HTTP请求</span>
                  <span class="command-example">curl -I example.com</span>
                </div>
                <div class="command-item">
                  <span class="command-name">wget</span>
                  <span class="command-desc">下载文件</span>
                  <span class="command-example">wget url</span>
                </div>
                <div class="command-item">
                  <span class="command-name">ssh</span>
                  <span class="command-desc">远程登录</span>
                  <span class="command-example">ssh user@host</span>
                </div>
                <div class="command-item">
                  <span class="command-name">scp</span>
                  <span class="command-desc">远程复制文件</span>
                  <span class="command-example">scp file user@host:path</span>
                </div>
              </div>

              <div class="command-category">
                <h4>终端操作</h4>
                <div class="command-item">
                  <span class="command-name">clear</span>
                  <span class="command-desc">清空终端屏幕</span>
                </div>
                <div class="command-item">
                  <span class="command-name">history</span>
                  <span class="command-desc">显示命令历史</span>
                </div>
                <div class="command-item">
                  <span class="command-name">help</span>
                  <span class="command-desc">显示帮助信息</span>
                </div>
                <div class="command-item">
                  <span class="command-name">exit</span>
                  <span class="command-desc">断开连接</span>
                </div>
              </div>
            </div>
          </el-collapse-transition>
        </div>
        <div class="connection-controls">
          <el-form :model="connectionForm" :rules="rules" ref="connectionForm" inline>
            <el-form-item prop="host">
              <el-input
                v-model="connectionForm.host"
                placeholder="主机地址"
                class="connection-input"
                size="small"
              >
                <template slot="prepend">主机</template>
              </el-input>
            </el-form-item>
            <el-form-item prop="port">
              <el-input
                v-model="connectionForm.port"
                placeholder="端口"
                class="connection-input"
                size="small"
              >
                <template slot="prepend">端口</template>
              </el-input>
            </el-form-item>
            <el-form-item prop="username">
              <el-input
                v-model="connectionForm.username"
                placeholder="用户名"
                class="connection-input"
                size="small"
              >
                <template slot="prepend">用户</template>
              </el-input>
            </el-form-item>
            <el-form-item prop="password">
              <el-input
                v-model="connectionForm.password"
                type="password"
                placeholder="密码"
                class="connection-input"
                size="small"
                @keyup.enter.native="connect"
              >系统
                <template slot="prepend">密码</template>
              </el-input>
            </el-form-item>
            <el-form-item>
              <el-button
                type="primary"
                size="small"
                :loading="connecting"
                @click="connect"
              >
                {{ isConnected ? '断开连接' : '连接' }}
              </el-button>
            </el-form-item>
          </el-form>
        </div>
      </div>

      <!-- 终端窗口 -->
      <div class="terminal-window" ref="terminalWindow">
        <div class="terminal-content" ref="terminalContent">
          <div v-for="(line, index) in terminalLines" :key="index" class="terminal-line">
            <span v-if="line.type === 'input'" class="prompt">$</span>
            <span :class="['line-content', line.type]">{{ line.content }}</span>
          </div>
          <div v-if="isConnected" class="terminal-line">
            <span class="prompt">$</span>
            <input
              ref="commandInput"
              v-model="currentCommand"
              class="command-input"
              @keyup.enter="executeCommand"
              @keydown.tab.prevent="handleTab"
              placeholder="输入命令..."
            />
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script>
import { executeSSHCommand, connectSSH } from '@/api/opration'

export default {
  name: 'SSH',
  data() {
    return {
      connectionForm: {
        host: '',
        port: '22',
        username: '',
        password: ''
      },
      rules: {
        host: [
          { required: true, message: '请输入主机地址', trigger: 'blur' },
          { pattern: /^(\d{1,3}\.){3}\d{1,3}$|^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/, message: '请输入有效的主机地址', trigger: 'blur' }
        ],
        port: [
          { required: true, message: '请输入端口号', trigger: 'blur' },
          { pattern: /^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/, message: '请输入有效的端口号(1-65535)', trigger: 'blur' }
        ],
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ]
      },
      connecting: false,
      isConnected: false,
      terminalLines: [],
      currentCommand: '',
      commandHistory: [],
      sessionId: '',
      commandSuggestions: [],
      showSuggestions: false,
      suggestionIndex: -1,
      showCommands: false
    }
  },
  created() {
    // 从本地存储加载上次的连接信息
    const savedConnection = localStorage.getItem('ssh_connection')
    if (savedConnection) {
      try {
        const { host, port, username } = JSON.parse(savedConnection)
        this.connectionForm = {
          ...this.connectionForm,
          host: host || '',
          port: port || '22',
          username: username || ''
        }
      } catch (error) {
        console.error('加载保存的连接信息失败:', error)
      }
    }
  },
  methods: {
    async connect() {
      if (this.isConnected) {
        this.disconnect()
        return
      }

      try {
        await this.$refs.connectionForm.validate()
      } catch (error) {
        return
      }

      this.connecting = true
      try {
        const response = await connectSSH(this.connectionForm)
        if (response.status === 'success') {
          // 保存连接信息到本地存储（不包含密码）
          const { password, ...connectionInfo } = this.connectionForm
          localStorage.setItem('ssh_connection', JSON.stringify(connectionInfo))
          
          this.isConnected = true
          this.sessionId = response.session_id
          this.addTerminalLine('已连接到服务器', 'system')
          this.$nextTick(() => {
            this.$refs.commandInput.focus()
          })
        } else {
          throw new Error(response.message || '连接失败')
        }
      } catch (error) {
        this.$message.error('连接失败：' + (error.message || '未知错误'))
      } finally {
        this.connecting = false
      }
    },
    disconnect() {
      this.isConnected = false
      this.sessionId = ''
      this.addTerminalLine('已断开连接', 'system')
      this.terminalLines = []
      // 不清除保存的连接信息，只重置表单
      this.$refs.connectionForm.resetFields()
      // 重新加载保存的连接信息
      const savedConnection = localStorage.getItem('ssh_connection')
      if (savedConnection) {
        try {
          const { host, port, username } = JSON.parse(savedConnection)
          this.connectionForm = {
            ...this.connectionForm,
            host: host || '',
            port: port || '22',
            username: username || ''
          }
        } catch (error) {
          console.error('加载保存的连接信息失败:', error)
        }
      }
    },
    async executeCommand() {
      if (!this.currentCommand.trim()) return

      const command = this.currentCommand
      this.addTerminalLine(command, 'input')
      this.commandHistory.push(command)
      this.currentCommand = ''

      // 处理内置命令
      const builtInCommands = {
        clear: () => {
          this.terminalLines = []
          this.$refs.terminalWindow.style.opacity = '0'
          setTimeout(() => {
            this.$refs.terminalWindow.style.opacity = '1'
          }, 300)
        },
        help: () => {
          this.addTerminalLine('可用命令：', 'system')
          this.addTerminalLine('clear - 清空终端屏幕', 'system')
          this.addTerminalLine('help - 显示帮助信息', 'system')
          this.addTerminalLine('history - 显示命令历史', 'system')
          this.addTerminalLine('exit - 断开连接', 'system')
        },
        history: () => {
          if (this.commandHistory.length === 0) {
            this.addTerminalLine('没有命令历史记录', 'system')
          } else {
            this.commandHistory.forEach((cmd, index) => {
              this.addTerminalLine(`${index + 1}  ${cmd}`, 'system')
            })
          }
        },
        exit: () => {
          this.disconnect()
        }
      }

      const cmd = command.trim()
      if (builtInCommands[cmd]) {
        builtInCommands[cmd]()
        return
      }

      try {
        const response = await executeSSHCommand({
          command,
          host: this.connectionForm.host,
          port: this.connectionForm.port,
          username: this.connectionForm.username,
          password: this.connectionForm.password,
          session_id: this.sessionId
        })
        
        if (response.output) {
          this.addTerminalLine(response.output, 'output')
        }
      } catch (error) {
        this.addTerminalLine('执行命令失败：' + error.message, 'error')
      }

      this.$nextTick(() => {
        this.scrollToBottom()
        this.$refs.commandInput.focus()
      })
    },
    addTerminalLine(content, type = 'output') {
      this.terminalLines.push({ content, type })
      this.$nextTick(() => {
        this.scrollToBottom()
      })
    },
    scrollToBottom() {
      const container = this.$refs.terminalWindow
      container.scrollTop = container.scrollHeight
    },
    handleTab(e) {
      if (!this.currentCommand.trim()) return
      
      e.preventDefault()
      const input = this.currentCommand.trim()
      const words = input.split(' ')
      const lastWord = words[words.length - 1]
      
      if (words.length === 1) {
        this.getCommandSuggestions(lastWord)
      } else {
        this.getSubCommandSuggestions(words[0], lastWord)
      }
    },
    async getCommandSuggestions(prefix) {
      try {
        const response = await executeSSHCommand({
          command: `compgen -c ${prefix}`,
          host: this.connectionForm.host,
          port: this.connectionForm.port,
          username: this.connectionForm.username,
          password: this.connectionForm.password,
          session_id: this.sessionId
        })
        
        if (response.output) {
          this.commandSuggestions = response.output.split('\n').filter(cmd => cmd.startsWith(prefix))
          this.showSuggestions = this.commandSuggestions.length > 0
          this.suggestionIndex = -1
          
          if (this.commandSuggestions.length === 1) {
            this.currentCommand = this.commandSuggestions[0]
          } else if (this.commandSuggestions.length > 1) {
            this.addTerminalLine(this.commandSuggestions.join('  '), 'system')
          }
        }
      } catch (error) {
        console.error('获取命令建议失败:', error)
      }
    },
    async getSubCommandSuggestions(command, prefix) {
      try {
        let compgenCommand = ''
        switch (command) {
          case 'pip':
            compgenCommand = `pip help | grep -E "^  ${prefix}" | awk '{print $1}'`
            break
          case 'git':
            compgenCommand = `git help -a | grep -E "^  ${prefix}" | awk '{print $1}'`
            break
          case 'docker':
            compgenCommand = `docker --help | grep -E "^  ${prefix}" | awk '{print $1}'`
            break
          default:
            compgenCommand = `compgen -c ${prefix}`
        }
        
        const response = await executeSSHCommand({
          command: compgenCommand,
          host: this.connectionForm.host,
          port: this.connectionForm.port,
          username: this.connectionForm.username,
          password: this.connectionForm.password,
          session_id: this.sessionId
        })
        
        if (response.output) {
          this.commandSuggestions = response.output.split('\n').filter(cmd => cmd.startsWith(prefix))
          this.showSuggestions = this.commandSuggestions.length > 0
          this.suggestionIndex = -1
          
          if (this.commandSuggestions.length === 1) {
            const words = this.currentCommand.split(' ')
            words[words.length - 1] = this.commandSuggestions[0]
            this.currentCommand = words.join(' ')
          } else if (this.commandSuggestions.length > 1) {
            this.addTerminalLine(this.commandSuggestions.join('  '), 'system')
          }
        }
      } catch (error) {
        console.error('获取子命令建议失败:', error)
      }
    },
    toggleCommands() {
      this.showCommands = !this.showCommands
    }
  }
}
</script>

<style lang="scss" scoped>
.ssh-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: calc(100vh - 84px);

  .ssh-card {
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);

    .card-header {
      .card-title {
        font-size: 16px;
        font-weight: bold;
        color: #303133;
        display: flex;
        align-items: center;

        i {
          margin-right: 8px;
          font-size: 18px;
          color: #409EFF;
        }
      }

      .common-commands {
        margin-top: 10px;
        cursor: pointer;
        user-select: none;

        .commands-title {
          display: flex;
          align-items: center;
          color: #606266;
          font-size: 14px;

          i {
            margin-right: 8px;
            font-size: 16px;
            color: #409EFF;

            &.el-icon-arrow-down {
              margin-left: 8px;
              transition: transform 0.3s;
              
              &.is-active {
                transform: rotate(180deg);
              }
            }
          }
        }

        .commands-list {
          margin-top: 10px;
          padding: 15px;
          background-color: #f5f7fa;
          border-radius: 4px;
          display: grid;
          grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
          gap: 20px;

          .command-category {
            h4 {
              margin: 0 0 10px;
              padding-bottom: 5px;
              border-bottom: 1px solid #dcdfe6;
              color: #303133;
              font-size: 14px;
            }

            .command-item {
              display: flex;
              align-items: center;
              padding: 8px;
              background-color: #fff;
              border-radius: 4px;
              box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
              margin-bottom: 8px;

              .command-name {
                font-family: 'Courier New', Courier, monospace;
                color: #409EFF;
                font-weight: bold;
                margin-right: 10px;
                min-width: 80px;
              }

              .command-desc {
                color: #606266;
                font-size: 13px;
                flex: 1;
              }

              .command-example {
                font-family: 'Courier New', Courier, monospace;
                color: #909399;
                font-size: 12px;
                margin-left: 10px;
                white-space: nowrap;
              }
            }
          }
        }
      }

      .connection-controls {
        display: flex;
        align-items: flex-start;
        margin-top: 15px;
        flex-wrap: wrap;
        gap: 10px;

        .el-form {
          display: flex;
          flex-wrap: wrap;
          gap: 10px;
        }

        .el-form-item {
          margin-bottom: 0;
        }

        .connection-input {
          width: 200px;
        }
      }
    }
  }

  .terminal-window {
    background-color: #1e1e1e;
    border-radius: 4px;
    height: 500px;
    overflow-y: auto;
    padding: 10px;
    font-family: 'Courier New', Courier, monospace;
    transition: opacity 0.3s ease;

    .terminal-content {
      color: #fff;

      .terminal-line {
        display: flex;
        align-items: flex-start;
        margin-bottom: 4px;
        line-height: 1.5;

        .prompt {
          color: #00ff00;
          margin-right: 8px;
        }

        .line-content {
          white-space: pre-wrap;
          word-break: break-all;

          &.input {
            color: #fff;
          }

          &.output {
            color: #ccc;
          }

          &.error {
            color: #ff4444;
          }

          &.system {
            color: #00ff00;
          }
        }

        .command-input {
          flex: 1;
          background: transparent;
          border: none;
          color: #fff;
          font-family: 'Courier New', Courier, monospace;
          font-size: 14px;
          outline: none;
          padding: 0;
          margin: 0;
          caret-color: #00ff00;

          &::placeholder {
            color: #666;
          }
        }
      }
    }
  }
}

// 自定义滚动条样式
.terminal-window::-webkit-scrollbar {
  width: 8px;
}

.terminal-window::-webkit-scrollbar-track {
  background: #2d2d2d;
}

.terminal-window::-webkit-scrollbar-thumb {
  background: #666;
  border-radius: 4px;
}

.terminal-window::-webkit-scrollbar-thumb:hover {
  background: #888;
}
</style> 